﻿using System;
using System.Linq;
using System.Text;
using XTemplate.Base.Model;
using XTemplate.Base.Param;
using XTemplate.Base.Respository;
using XTemplate.Utils.Extensions;

namespace XTemplate.Base.Services
{
    public class TableGeneratorService
    {
        private readonly string AuthorComment = @"/**
 * 此文件由代码生成服务生成
 *
 * Author:  星风
 * Date:    {0}
 */";

        private readonly string NameSpaceSystem = "using System;";
        private readonly string NameSpaceDataAnnotations = "using System.ComponentModel.DataAnnotations;";
        private readonly string NameSpaceDataAnnotationsSchema = "using System.ComponentModel.DataAnnotations.Schema;";

        private readonly string AttributeAnnotationsTable = "[Table(\"{0}\")]";
        private readonly string AttributeAnnotationsColumn = "[Column(\"{0}\")]";
        private readonly string AttributeAnnotationsColumnWithType = "[Column(\"{0}\", TypeName=\"{1}\")]";

        private readonly string AttributeAnnotationsSchemaMaxLength = "[MaxLength({0})]";
        private readonly string AttributeAnnotationsSchemaRequired = "[Required(AllowEmptyStrings = false, ErrorMessage=\"{0} 不能为空\")]";
        private readonly string AttributeAnnotationsSchemaKey = "[Key]";

        private readonly string XmlCommentStart = "/// <summary>";
        private readonly string XmlCommentContent = "/// {0}";
        private readonly string XmlCommentEnd = "/// </summary>";

        private readonly string NameSpace = "namespace {0}";
        private readonly string Class = "public class {0}";
        private readonly string Property = "public {0} {1} {{ get; set; }}";

        private readonly TableGeneratorRepository _tableGeneratorRespository;

        public TableGeneratorService(TableGeneratorRepository tableGeneratorRespository)
        {
            _tableGeneratorRespository = tableGeneratorRespository;
        }

        public TableGenerateModel GenerateTableSchema(TableGenerateParam tableGenerateParam)
        {
            var tables = _tableGeneratorRespository.GetTableInfo(tableGenerateParam.TableSchema).ToList();
            var ret = new TableGenerateModel()
            {
                TableSchema = tableGenerateParam.TableSchema,
                NameSpace = tableGenerateParam.NameSpace,
                Path = tableGenerateParam.Path,
                TableGenerateResult = new System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<string, string>>()
            };

            foreach (var item in tables)
            {
                ret.TableGenerateResult.Add(
                    new System.Collections.Generic.KeyValuePair<string, string>(
                        item.TableName, GenerateTableInfo(item.TableName, tableGenerateParam.NameSpace, tableGenerateParam.TableSchema)
                        ));
            }

            return ret;
        }

        public string GenerateTableInfo(string tableName, string nameSpace, string tableSchema = "")
        {
            var tableInfo = _tableGeneratorRespository.GetTableColumnInfo(tableName, tableSchema).ToList();

            var sb = new StringBuilder();
            sb.AppendLine(string.Format(AuthorComment, DateTime.Now));
            sb.AppendLine();
            sb.AppendLine(NameSpaceSystem);
            sb.AppendLine(NameSpaceDataAnnotations);
            sb.AppendLine(NameSpaceDataAnnotationsSchema);
            sb.AppendLine();
            sb.AppendLine(string.Format(NameSpace, nameSpace));
            sb.AppendLine("{");
            sb.AppendLine("\t" + string.Format(AttributeAnnotationsTable, tableName));
            sb.AppendLine("\t" + string.Format(Class, $"{tableName.UpCamelName()}Entity"));
            sb.AppendLine("\t" + "{");
            foreach (var item in tableInfo)
            {
                sb.AppendLine("\t\t" + XmlCommentStart);
                sb.AppendLine("\t\t" + string.Format(XmlCommentContent, item.ColumnCNName));
                sb.AppendLine("\t\t" + XmlCommentEnd);
                if (item.ColumnKey == "PRI")// TODO: 主键的长度没有识别
                    sb.AppendLine("\t\t" + AttributeAnnotationsSchemaKey);
                sb.AppendLine("\t\t" + string.Format(AttributeAnnotationsColumnWithType, item.ColumnName, item.DBColumnType));
                if (item.MaxLength != null && item.MaxLength != "0")
                    sb.AppendLine("\t\t" + string.Format(AttributeAnnotationsSchemaMaxLength, item.MaxLength));
                if (item.Nullable || item.ColumnKey == "PRI")
                    sb.AppendLine("\t\t" + AttributeAnnotationsSchemaRequired);
                sb.AppendLine("\t\t" + string.Format(Property, item.ColumnType, item.ColumnName.UpCamelName()));
                sb.AppendLine();
            }
            sb.AppendLine("\t" + "}");
            sb.AppendLine("}");

            return sb.ToString();
        }
    }
}